const Section = require('../entity/product/section');
const Product = require('../entity/product/product');
const Collection = require('../entity/product/collection');
const CartItem = require('../entity/product/cartitem');
const Leaderboard = require('../entity/product/leaderboard');
const SecKillOrder = require('../entity/product/seckillorder');
const Order = require('../entity/product/order');

const { CommonServiceError } = require('../module/error/svcerror');

const ProductType = require('../module/const/ProductType');
const moment = require('moment/moment');

// =========================== 栏目（已优化） ===============================
// 查询栏目列表列表
async function sectionList (areaId) {
    const SectionModel = new Section().getModel();
    const sectionData = await SectionModel.find({ areaId, isEnable: true }).sort({ sort: -1 });

    const ProductModel = new Product().getModel();
    return Promise.all(sectionData.map(async v => {
        const productList = await ProductModel.find({ _id: { $in: v.productList }, isEnable: true, isDelete: false, productType: 1 }).sort({ sort: -1 });
        return {
            ...v.toObject(),
            productList: productList
        };
    }));
}
// 查询热力排行榜产品
async function heatLeaderboard (areaId) {
    const LeaderboardModel = new Leaderboard().getModel();
    return LeaderboardModel.aggregate([
        {
            $match: {
                areaId: Leaderboard.toObjectId(areaId),
                isEnable: true
            }
        },
        {
            $sort: {
                sort: 1
            }
        },
        {
            $lookup: {
                from: 'product',
                localField: 'productId',
                foreignField: '_id',
                as: 'product'
            }
        },
        {
            $unwind: '$product'
        }
    ]);
}

// =========================== 产品收藏（已优化） ===============================
// 收藏或取消收藏商品
async function collectProduct (userId, areaId, productId) {
    const CollectionEntity = new Collection();
    const CollectionModel = CollectionEntity.getModel();

    const data = await CollectionModel.findOne({ userId, areaId, productId });
    if (data) {
        await CollectionModel.findByIdAndDelete(data._id);
    } else {
        await CollectionEntity.getDoc({ userId, areaId, productId }).save();
    }
    return 1;
}
// 客户是否收藏该产品
async function productHasCollected (userId, areaId, productId) {
    const CollectionModel = new Collection().getModel();
    return CollectionModel.exists({ userId, areaId, productId });
}
// 收藏列表
async function collectList (userId, areaId) {
    const CollectionModel = new Collection().getModel();
    return CollectionModel.aggregate([
        {
            $match: {
                userId: Collection.toObjectId(userId),
                areaId: Collection.toObjectId(areaId)
            }
        },
        {
            $sort: { createTime: -1 }
        },
        {
            $lookup: {
                from: 'product',
                localField: 'productId',
                foreignField: '_id',
                as: 'product'
            }
        },
        {
            $unwind: '$product'
        },
        {
            $replaceRoot: {
                newRoot: '$product'
            }
        },
        {
            $match: {
                isDelete: false,
                isEnable: true
            }
        }
    ]);
}

// =========================== 购物车逻辑（已优化） ===============================
// 购物车加入商品 --已优化
async function addSkuToCart (userId, areaId, productId, skuId) {
    const ProductModel = new Product().getModel();
    const CartItemModel = new CartItem().getModel();

    // 产品数据
    const productData = await ProductModel.findById(productId);
    if (productData.inventory < 1) {
        throw new CommonServiceError('该产品库存不足！');
    }

    // 是否以秒杀价加入购物车
    let isSecKillPrice = false;

    // 产品是秒杀产品
    if (productData.productType === ProductType.SecKill) {
        const todayBeginTime = moment().startOf('day').valueOf();
        const todayEndTime = moment().endOf('day').valueOf();

        // 今天购买的秒杀产品
        const SecKillOrderRecordModel = new SecKillOrder().getModel();
        const secKillOrderRecordList = await SecKillOrderRecordModel.find({ createTime: { $gt: todayBeginTime / 1000, $lt: todayEndTime / 1000 } });

        // 【购物车】购物车是否有其他秒杀产品
        const cartHasOtherProduct = await CartItemModel.exists({ userId, productId: { $ne: productId }, skuId: { $ne: skuId }, isSecKillPrice: true });
        // 【购买记录】是否以秒杀价购买过其他秒杀产品
        let hasByOtherSkillProduct = secKillOrderRecordList.length > 0 && secKillOrderRecordList.some(orderItem => orderItem.productId.toString() !== productId);

        if (cartHasOtherProduct || hasByOtherSkillProduct) {
            isSecKillPrice = false;
        } else {
            // 【购物车】该秒杀产品在购物车里面的数量
            const currentProductCartCount = await CartItemModel.countDocuments({ userId, productId, skuId, isSecKillPrice: true });
            // 【购买记录】今天购买该秒杀产品的数量
            const todayBuyCount = secKillOrderRecordList.reduce((pre, cur) => pre + (cur.productId.toString() === productId ? cur.count : 0), 0);
            isSecKillPrice = todayBuyCount < productData.quantityLimit && currentProductCartCount < productData.quantityLimit;
        }
    }

    // 需要创建新的购物车信息
    if (!await CartItemModel.exists({ userId, productId, skuId, isSecKillPrice })) {
        return CartItemModel.create({ userId, areaId, productId, skuId, count: 1, isSecKillPrice });
    } else {
        const cartItemData = await CartItemModel.findOne({ userId, productId, skuId, isSecKillPrice });
        return CartItemModel.findByIdAndUpdate(cartItemData._id, { $inc: { count: 1 } });
    }
}
// 购物车扣除商品 --已优化
async function subtractSkuFromCart (userId, areaId, productId, skuId) {
    const ProductModel = new Product().getModel();
    const CartItemModel = new CartItem().getModel();

    // 产品数据
    const productData = await ProductModel.findById(productId);

    let isSecKillPrice = false;
    if (productData.productType === ProductType.SecKill) {
        const notSecKillProductProductCount = await CartItemModel.countDocuments({ userId, productId, skuId, isSecKillPrice: false });
        isSecKillPrice = notSecKillProductProductCount <= 0;
    }

    let cartItemData = await CartItemModel.findOne({ userId, productId, skuId, isSecKillPrice });
    if (cartItemData.count > 1) {
        await CartItemModel.findByIdAndUpdate(cartItemData._id, { $inc: { count: -1 } });
    } else {
        await CartItemModel.findByIdAndRemove(cartItemData._id);
    }
    return 1;
}
// 移除购物车信息（下完单后清空购物车信息）
async function removeCartItem (cartItemIdList) {
    const CartItemModel = new CartItem().getModel();
    await CartItemModel.remove({ _id: { $in: cartItemIdList } });
    return 1;
}
// todo 查询购物车信息，需返回失效的商品
async function cartInfo (userId, areaId) {
    const CartItemModel = new CartItem().getModel();
    const ProductModel = new Product().getModel();

    const cartItemList = await CartItemModel.find({ userId, areaId }).sort({ createTime: -1 });

    const validCartItemList = await Promise.all(cartItemList.filter(async v => {
        const productData = await ProductModel.findById(v.productId);
        // 【下架，删除，库存小于1】删除购物车信息
        if (!productData.isEnable || productData.isDelete || productData.inventory < 1) {
            await CartItemModel.remove({ _id: v });
            return false;
        }
        return true;
    }));
    return assembleCartInfo(validCartItemList.map(v => v._id));
}
// 组合购物车信息
async function assembleCartInfo (newCartItemIdList) {
    const CartItemModel = new CartItem().getModel();
    const ProductModel = new Product().getModel();

    return Promise.all(newCartItemIdList.map(async cartId => {
        const cartInfo = await CartItemModel.findById(cartId);
        const productData = await ProductModel.findById(cartInfo.productId);
        const skuInfo = productData.skus.find(v => v.id === cartInfo.skuId);
        return {
            cartInfo: cartInfo.toObject(),
            productData: productData.toObject(),
            skuInfo
        };
    }));
}

// =========================== 库存管理 ===============================
// 扣减库存 --已优化
async function reduceInventory (productList) {
    const ProductModel = new Product().getModel();
    for await (const item of productList) {
        const productData = await ProductModel.findById(item.productId);
        // 本次消耗库存数量
        const consumeInventory = item.count * item.inventory;
        // 剩余库存数
        const remainInventory = productData.inventory;

        productData.inventory = remainInventory - consumeInventory;
        if (remainInventory - consumeInventory <= 0) {
            productData.isEnable = false;
        }
        await productData.save();
    }
    return 1;
}
// 退回库存 --已优化
async function increaseInventory (orderId) {
    const OrderModel = new Order().getModel();
    const orderData = await OrderModel.findById(orderId);

    if (!orderData) {
        throw new CommonServiceError('订单不存在');
    }

    const ProductModel = new Product().getModel();
    for await (const item of orderData.productList) {
        await ProductModel.updateOne(
            { _id: item.productId },
            { $inc: { inventory: item.count * item.inventory }, isEnable: true });
    }
    return 1;
}

// -----------------
/**
 * 查询随机个数商品
 * @param areaId 城市ID
 * @param size 数量
 * @returns {Promise<*>}
 */
async function randomProduct (areaId, size) {
    size = parseInt(size);
    const ProductEntity = new Product();
    const ProductModel = ProductEntity.getModel();
    return ProductModel.aggregate([
        {
            $match: {
                areaId: Product.toObjectId(areaId),
                isDelete: false,
                productType: ProductType.Ordinary
            }
        },
        {
            $sample: {
                size
            }
        }
    ]);
}

module.exports = {
    sectionList,
    collectProduct,
    productHasCollected,
    collectList,
    addSkuToCart,
    subtractSkuFromCart,
    cartInfo,
    assembleCartInfo,
    removeCartItem,
    heatLeaderboard,
    reduceInventory,
    increaseInventory,
    randomProduct
};
